package com.lemon.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.lemon.domain.StocktakingTask;
import com.lemon.domain.WarehousingEntryUp;
import com.lemon.domain.dto.AddStocktakingDto;
import com.lemon.mapper.StocktakingTaskMapper;
import com.lemon.mapper.WarehousingEntryUpMapper;
import com.lemon.service.StocktakingInfoService;
import com.lemon.service.WarehousingEntryUpService;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;

@Component
public class TaskSchedulerService {
    
    @Autowired
    private StocktakingTaskMapper stocktakingTaskMapper;
    
    // 任务调度器
    @Autowired
    private TaskScheduler taskScheduler;

    @Autowired
    private StocktakingInfoService stocktakingInfoService;

    @Autowired
    private WarehousingEntryUpMapper warehousingEntryUpMapper;
    
    // 存储已调度的任务
    private final Map<Long, ScheduledFuture<?>> scheduledTasks = new ConcurrentHashMap<>();
    
    /**
     * 调度定时任务
     */
    public void scheduleTask(StocktakingTask task) {
        // 如果任务已存在，先取消
        cancelTask(task.getId());
        
        try {
            // 创建任务Runnable
            Runnable taskRunnable = createTaskRunnable(task);
            
            // 解析cron表达式
            CronTrigger cronTrigger = new CronTrigger(task.getCronExpression());
            
            // 调度任务
            ScheduledFuture<?> scheduledFuture = taskScheduler.schedule(taskRunnable, cronTrigger);
            
            // 存储任务引用
            scheduledTasks.put(task.getId(), scheduledFuture);
            
        } catch (Exception e) {
            throw new RuntimeException("调度任务失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 取消定时任务
     */
    public void cancelTask(Long taskId) {
        ScheduledFuture<?> scheduledFuture = scheduledTasks.get(taskId);
        if (scheduledFuture != null) {
            scheduledFuture.cancel(false);
            scheduledTasks.remove(taskId);
        }
    }
    
    /**
     * 重新调度任务
     */
    public void rescheduleTask(StocktakingTask task) {
        // 先取消现有任务
        cancelTask(task.getId());
        
        // 如果任务启用，则重新调度
        if (task.getIsEnable() == 1) {
            scheduleTask(task);
        }
    }
    
    /**
     * 创建任务执行逻辑
     */
    private Runnable createTaskRunnable(StocktakingTask task) {
        return () -> {
            try {
                // 执行具体的盘点逻辑
                executeStocktakingTask(task);
            } catch (Exception e) {
                // 记录错误日志
                System.err.println("执行定时盘点任务失败: " + e.getMessage());
                e.printStackTrace();
            }
        };
    }
    
    /**
     * 执行具体的盘点任务逻辑
     */
    public void executeStocktakingTask(StocktakingTask task) {
        System.out.println("开始执行盘点任务: " + task.getTaskName());
        System.out.println("任务类型: " + getCategoryName(task.getCategory()));
        // 根据category类型执行不同的盘点逻辑
        switch (task.getCategory()) {
            case 1:
                // 仓库盘点逻辑
                performWarehouseStocktaking(task);
                break;
            case 2:
                // 库区盘点逻辑
                performAreaStocktaking(task);
                break;
            case 3:
                // 库位盘点逻辑
                performLocationStocktaking(task);
                break;
            default:
                System.out.println("未知的盘点类型: " + task.getCategory());
        }
    }
    
    /**
     * 仓库盘点
     */
    private void performWarehouseStocktaking(StocktakingTask task) {
        // 实现仓库盘点逻辑
        List<WarehousingEntryUp> upList = warehousingEntryUpMapper.selectList(Wrappers.<WarehousingEntryUp>lambdaQuery().eq(WarehousingEntryUp::getWarehouseId, task.getTargetId()));
        upList.forEach(up -> {
            StocktakingTask stocktakingTask = new StocktakingTask();
            stocktakingTask.setTargetId(up.getWarehouseAreaId());
            performAreaStocktaking(stocktakingTask);
        });
    }
    
    /**
     * 库区盘点
     */
    private void performAreaStocktaking(StocktakingTask task) {
        // 实现库区盘点逻辑
        List<WarehousingEntryUp> upList = warehousingEntryUpMapper.selectList(Wrappers.<WarehousingEntryUp>lambdaQuery().eq(WarehousingEntryUp::getWarehouseAreaId, task.getTargetId()));
        upList.forEach(up -> {
            StocktakingTask stocktakingTask = new StocktakingTask();
            stocktakingTask.setTargetId(up.getWarehouseAreaLocaId());
            performLocationStocktaking(stocktakingTask);
        });
    }
    
    /**
     * 库位盘点
     */
    private void performLocationStocktaking(StocktakingTask task) {
        // 实现库位盘点逻辑
        List<WarehousingEntryUp> upList = warehousingEntryUpMapper.selectList(Wrappers.<WarehousingEntryUp>lambdaQuery().eq(WarehousingEntryUp::getWarehouseAreaLocaId, task.getTargetId()));
        List<AddStocktakingDto> list = new ArrayList<>();
        upList.forEach(warehousingEntryUp -> {
            AddStocktakingDto dto = new AddStocktakingDto();
            dto.setSkuId(warehousingEntryUp.getSkuId());
            dto.setTargetWarehouseAreaLocaId(Long.valueOf(task.getTargetId()));
            dto.setIsCategory(2);
            list.add(dto);
        });
        stocktakingInfoService.add(list);
    }
    
    /**
     * 获取盘点类型名称
     */
    private String getCategoryName(Integer category) {
        switch (category) {
            case 1: return "仓库盘点";
            case 2: return "库区盘点";
            case 3: return "库位盘点";
            default: return "未知类型";
        }
    }
    
    /**
     * 初始化时加载所有启用的定时任务
     */
    @PostConstruct
    public void initScheduledTasks() {
        // 查询所有启用且未删除的任务
        List<StocktakingTask> tasks = stocktakingTaskMapper.selectEnabledTasks();
        
        for (StocktakingTask task : tasks) {
            if (task.getIsEnable() == 1) {
                try {
                    scheduleTask(task);
                } catch (Exception e) {
                    System.err.println("初始化定时任务失败: " + task.getTaskName() + ", 错误: " + e.getMessage());
                }
            }
        }
    }
}
